#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/un.h> 
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h> 
#include <arpa/inet.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <math.h>
#include <pthread.h>

#include "estructuras.h"
#include "constantes.h"
#include "sockets.h"
#include "configuracion.h"
#include "estadisticas.h"
#include "listas.h"
#include "NIPC.h"

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

extern chs glChs;
extern int glRPM;

int posicionCabezal;
int activaEnAtencion;

void * AtenderPedido (void *args); 
void * AtenderPedido_CSCAN (void *args); 

void * AtenderPedido (void *args)
{
	InfoIPC infoIPC;
	int *pSocketConectado;
	sectoresIntermedios listaSectoreYTiempos;
	int f,i,payload;
	
	colas2 *q = (colas2 *) args;
	char *sSocket=(char *)malloc(10);
	char *auxread=(char *)malloc(512);
	char *sSector=(char *)malloc(20);

	while(1)
	{		
		if(!(estaVacia(q->activacabeza))){
			
			activaEnAtencion=1;
			struct ListaIDdescriptors * nodoaAtender;
		
			
			/*
			printf("\n\n\n\nEn hilo de atencion antes lock activa\n\n\n\n\n\n");
			
			if(pthread_mutex_lock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
			}
			
			ordenarListaCSCAN(&(q->activacabeza),&(q->activacola));
			
			printf("\n\n\n\nEn hilo de atencion tras lock ordenarLISTAactiva\n\n\n\n\n");
			
			
			if(pthread_mutex_unlock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
			}
			
			
			printf("\n\n\n\nEn hilo de atencion tras unlock activa\n\n\n\n\n");
			*/
			
			if(pthread_mutex_lock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
			}
					
			/*ordenarListaCSCAN(&(q->activacabeza),&(q->activacola));*/
			nodoaAtender=SacarNodoDescriptoresDeLista(&q->activacabeza,&q->activacola);
			
			if(pthread_mutex_unlock(&mutex)!=0){
					perror("pthread_mutex_unlock");
					exit(EXIT_FAILURE);
			}
			
			/*
			listaSectoreYTiempos = SectoresIntermedios_Actualiza(&posicionCabezal,nodoaAtender->sector,glChs,glRPM);
			printf("SECTORES LEIDOS: ");
			for( f = 0;f < listaSectoreYTiempos.tamanioVector;f++)
			{
				printf("%d |", listaSectoreYTiempos.ptrSectoresLeidos[f]);
			}
			printf("\n");

			printf("TIEMPO CONSUMIDO: %f ms\n",listaSectoreYTiempos.tiempoDeAcceso);
			*/
			
			if((nodoaAtender->operacion == 0)||(nodoaAtender->operacion == 1))
			{
				
				infoIPC.payLoadLength=strlen(nodoaAtender->sDescriptorID_delPedido)+1;
				generarStructIPC(nodoaAtender->sDescriptorID_delPedido,NUMEROPEDIDO,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
					
			}
			if(nodoaAtender->operacion == 0)
			{
				
				if(atoi(nodoaAtender->sDescriptorID_delPedido)!=-1){
					printf("Leer Sector: %i \n", nodoaAtender->sector);
					payload=RTA_READ_SECTOR_REQUEST;
				}
				else{
					printf("Leer Sector SYNC: %i\n", nodoaAtender->sector);
					payload=RTA_READ_SECTORSYNC_REQUEST;
				}
				
				memcpy(auxread,readSector(nodoaAtender->sector), 512);
				printf("DATA LEIDA\n");
				printf("----------\n");
				printf("%s \n", auxread);
				
				intacad(nodoaAtender->sector,sSector);
				infoIPC.payLoadLength=strlen(sSector)+1;
				generarStructIPC(sSector,payload,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
				
				infoIPC.payLoadLength=512;
				generarStructIPC(auxread,payload,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
				
			}
			if(nodoaAtender->operacion == 1)
			{
				if(atoi(nodoaAtender->sDescriptorID_delPedido)!=-1){
					printf("Escribir Sector: %i - %s\n", nodoaAtender->sector, nodoaAtender->data);
					payload=RTA_WRITE_SECTOR_REQUEST;
				}	
				else{
					printf("Escribir SectorSYNC: %i - %s\n", nodoaAtender->sector, nodoaAtender->data);
					payload=RTA_WRITE_SECTORSYNC_REQUEST;
				}
				
				writeSector(nodoaAtender->sector, nodoaAtender->data);
				
				intacad(nodoaAtender->sector,sSector);
				infoIPC.payLoadLength=strlen(sSector)+1;
				generarStructIPC(sSector,payload,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
					
			}
					
			posicionCabezal=nodoaAtender->sector + 1;		
			free(nodoaAtender);		
		}
		else{
			
			if(!(estaVacia(q->pasivacabeza))){
				
				activaEnAtencion=0;
				
				while(q->pasivacabeza!=NULL){
				
					struct ListaIDdescriptors* nodo;
					
					if(pthread_mutex_lock(&mutex2)!=0){
						perror("pthread_mutex_lock");
						exit(EXIT_FAILURE);
					}
					if(pthread_mutex_lock(&mutex)!=0){
						perror("pthread_mutex_lock");
						exit(EXIT_FAILURE);
					}
					
					nodo=SacarNodoDescriptoresDeLista(&q->pasivacabeza,&q->pasivacola);
					AgregarAColaDePedidosADisco(&nodo,&q->activacabeza,&q->activacola);  
					
					if(pthread_mutex_unlock(&mutex)!=0){
						perror("pthread_mutex_lock");
						exit(EXIT_FAILURE);
					}
					if(pthread_mutex_unlock(&mutex2)!=0){
						perror("pthread_mutex_lock");
						exit(EXIT_FAILURE);
					}	
				}		
			}
		
		}
	}	
}


/*
void * AtenderPedido (void *args)
{
	fd_set master;	
	InfoIPC infoIPC;
	int *pSocketConectado;
	
	sectoresIntermedios listaSectoreYTiempos;
	int f,i;
	
	colas *q = (colas *) args;
	
	char *auxread=(char *)malloc(512);
	
	
	
	while(1)
	{		
		if(!(estaVacia(q->cabeza))){
			
			struct ListaIDdescriptors * nodoaAtender;
			
			if(pthread_mutex_lock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
			}
			
			nodoaAtender=SacarNodoDescriptoresDeLista(&q->cabeza,&q->cola);
			
			if(pthread_mutex_unlock(&mutex)!=0){
					perror("pthread_mutex_unlock");
					exit(EXIT_FAILURE);
			}
			
			listaSectoreYTiempos = SectoresIntermedios_Actualiza(&posicionCabezal,nodoaAtender->sector,glChs,glRPM);
			printf("SECTORES LEIDOS: ");
			for( f = 0;f < listaSectoreYTiempos.tamanioVector;f++)
			{
				printf("%d |", listaSectoreYTiempos.ptrSectoresLeidos[f]);
			}
			printf("\n");

			printf("TIEMPO CONSUMIDO: %f ms\n",listaSectoreYTiempos.tiempoDeAcceso);
			
 
		
			if(nodoaAtender->operacion == 0)
			{
				printf("Leer Sector: %i - ", nodoaAtender->sector);
				memset(auxread,'\0',512);
				memcpy(auxread,readSector(nodoaAtender->sector), 512);
				printf("%s\n", auxread);
			}
			if(nodoaAtender->operacion == 1)
			{
				printf("Escribir Sector: %i - %s\n", nodoaAtender->sector, nodoaAtender->data);
				writeSector(nodoaAtender->sector, nodoaAtender->data);
			}
			*/
			/*
			generarStructIPC(auxread,RTA_GET_SECTORES,&infoIPC);
			enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);
			*/
			/*
			posicionCabezal=nodoaAtender->sector + 1;		
			
			free(nodoaAtender);		
		}
	}
	free(auxread); 	
  
}	
*/


void * AtenderPedido_CSCAN (void *args)
{
	InfoIPC infoIPC;
	int *pSocketConectado;
	sectoresIntermedios listaSectoreYTiempos;
	int f,i,payload;
	
	colas *q = (colas *) args;
	char *sSocket=(char *)malloc(10);
	char *auxread=(char *)malloc(512);
	char *sSector=(char *)malloc(20);

	while(1)
	{		
		if(!(estaVacia(q->cabeza))){
			
			activaEnAtencion=1;
			struct ListaIDdescriptors * nodoaAtender;
		
			
			/*
			printf("\n\n\n\nEn hilo de atencion antes lock activa\n\n\n\n\n\n");
			
			if(pthread_mutex_lock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
			}
			
			ordenarListaCSCAN(&(q->cabeza),&(q->cola));
			
			printf("\n\n\n\nEn hilo de atencion tras lock ordenarLISTAactiva\n\n\n\n\n");
			
			
			if(pthread_mutex_unlock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
			}
			
			
			printf("\n\n\n\nEn hilo de atencion tras unlock activa\n\n\n\n\n");
			*/
			
			if(pthread_mutex_lock(&mutex)!=0){
					perror("pthread_mutex_lock");
					exit(EXIT_FAILURE);
			}
					
			/*ordenarListaCSCAN(&(q->cabeza),&(q->cola));*/
			nodoaAtender=SacarNodoDescriptoresDeLista(&q->cabeza,&q->cola);
			
			if(pthread_mutex_unlock(&mutex)!=0){
					perror("pthread_mutex_unlock");
					exit(EXIT_FAILURE);
			}
			
			/*
			listaSectoreYTiempos = SectoresIntermedios_Actualiza(&posicionCabezal,nodoaAtender->sector,glChs,glRPM);
			printf("SECTORES LEIDOS: ");
			for( f = 0;f < listaSectoreYTiempos.tamanioVector;f++)
			{
				printf("%d |", listaSectoreYTiempos.ptrSectoresLeidos[f]);
			}
			printf("\n");

			printf("TIEMPO CONSUMIDO: %f ms\n",listaSectoreYTiempos.tiempoDeAcceso);
			*/
			
			if((nodoaAtender->operacion == 0)||(nodoaAtender->operacion == 1))
			{
				
				infoIPC.payLoadLength=strlen(nodoaAtender->sDescriptorID_delPedido)+1;
				generarStructIPC(nodoaAtender->sDescriptorID_delPedido,NUMEROPEDIDO,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
					
			}
			if(nodoaAtender->operacion == 0)
			{
				
				if(atoi(nodoaAtender->sDescriptorID_delPedido)!=-1){
					printf("Leer Sector: %i \n", nodoaAtender->sector);
					payload=RTA_READ_SECTOR_REQUEST;
				}
				else{
					printf("Leer Sector SYNC: %i\n", nodoaAtender->sector);
					payload=RTA_READ_SECTORSYNC_REQUEST;
				}
				
				memset(auxread,'\0',512);
				memcpy(auxread,readSector(nodoaAtender->sector), 512);
				/*printf("DATA LEIDA\n");
				printf("----------\n");
				printf("%s \n", auxread);*/
				
				intacad(nodoaAtender->sector,sSector);
				infoIPC.payLoadLength=strlen(sSector)+1;
				generarStructIPC(sSector,payload,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
				
				infoIPC.payLoadLength=512;
				generarStructIPC(auxread,payload,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
				
			}
			if(nodoaAtender->operacion == 1)
			{
				if(atoi(nodoaAtender->sDescriptorID_delPedido)!=-1){
					printf("Escribir Sector: %i - %s\n", nodoaAtender->sector, nodoaAtender->data);
					payload=RTA_WRITE_SECTOR_REQUEST;
				}	
				else{
					printf("Escribir SectorSYNC: %i - %s\n", nodoaAtender->sector, nodoaAtender->data);
					payload=RTA_WRITE_SECTORSYNC_REQUEST;
				}
				
				writeSector(nodoaAtender->sector, nodoaAtender->data);
				
				intacad(nodoaAtender->sector,sSector);
				infoIPC.payLoadLength=strlen(sSector)+1;
				generarStructIPC(sSector,payload,&infoIPC);
				enviarIPC(atoi(nodoaAtender->sSocketPorElCualResponder),&infoIPC);	
					
			}
					
			posicionCabezal=nodoaAtender->sector + 1;		
			free(nodoaAtender);		
		}
	}	
}